package com.jun.admin.core.utils;

import com.alibaba.excel.context.AnalysisContext;
import com.jun.admin.core.model.excel.anno.*;
import com.jun.common.core.exception.ServiceException;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Objects;

/**
 * @author yuejun.li
 * @date 2024/10/9 14:54:14
 * Excel导入单元格校验
 */
public class ExcelValidUtil {

    /**
     * Excel导入字段校验
     * @param object 校验的JavaBean 其属性须有自定义注解
     * @param analysisContext excel的上下文属性
     */
    public static boolean valid(Object object, AnalysisContext analysisContext) {
        //反射获得对象的属性字段
        Field[] declaredFields = object.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            //设置可访问
            field.setAccessible(true);
            //属性值
            Object fieldValue;

            try{
                fieldValue = field.get(object);
            } catch (IllegalAccessException e) {
                throw new ServiceException("解析失败，请检查");
            }

            //是否包含必填校验注解
            boolean isExcelValid = field.isAnnotationPresent(ExcelRequiredValid.class);
            if (isExcelValid && Objects.isNull(fieldValue)) {
                throw new ServiceException(String.format("第%s行字段为空，请核实", analysisContext.readRowHolder().getRowIndex()));
            }

            //是否包含字符串长度校验注解
            boolean isExcelStrValid = field.isAnnotationPresent(ExcelStrValid.class);
            if (isExcelStrValid) {
                String cellStr = fieldValue.toString();
                int length = field.getAnnotation(ExcelStrValid.class).length();
                if (StringUtils.isNotBlank(cellStr) && cellStr.length() > length) {
                    throw new ServiceException(String.format("第%s行字段过长错误，请核实", analysisContext.readRowHolder().getRowIndex()));
                }
            }

            //是否包含日期格式校验注解
            boolean isExcelDateFormatValid = field.isAnnotationPresent(ExcelDateFormatValid.class);
            if (isExcelDateFormatValid) {
                // 若输入的时间字段被excel自动格式化了
                if(!(fieldValue instanceof Date)) {
                    throw new ServiceException(String.format("第%s行字段格式错误，请核实", analysisContext.readRowHolder().getRowIndex() + 1));
                }
                else if(!(fieldValue instanceof LocalDateTime)) {
                    throw new ServiceException(String.format("第%s行字段格式错误，请核实", analysisContext.readRowHolder().getRowIndex() + 1));
                }
                else if(!(fieldValue instanceof LocalDate)){
                    throw new ServiceException(String.format("第%s行字段格式错误，请核实", analysisContext.readRowHolder().getRowIndex() + 1));
                }
                else {
                    // 若没被excel转换，则传入的为String类型
                    String cellStr = fieldValue.toString();
                    String df = field.getAnnotation(ExcelDateFormatValid.class).format();
                    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(df);
                    try {
                        dateTimeFormatter.parse(cellStr);  // 如果报错则说明输入的时间格式有问题
                    }catch (Exception e) {
                        throw new ServiceException(String.format("第%s行字段格式错误，请核实", analysisContext.readRowHolder().getRowIndex() + 1));
                    }
                }
            }

            //是否包含int类型校验注解
            boolean isExcelIntValid = field.isAnnotationPresent(ExcelIntValid.class);
            if (isExcelIntValid) {
                if (fieldValue instanceof Integer) {
                    int cellInt = Integer.parseInt(fieldValue.toString());
                    int min = field.getAnnotation(ExcelIntValid.class).min();
                    int max = field.getAnnotation(ExcelIntValid.class).max();
                    if (cellInt < min) {
                        throw new ServiceException(String.format("第%s行字段过小，请核实", analysisContext.readRowHolder().getRowIndex() + 1));
                    }
                    if (cellInt > max) {
                        throw new ServiceException(String.format("第%s行字段过大，请核实", analysisContext.readRowHolder().getRowIndex() + 1));
                    }
                }
            }
            //是否包含decimal类型注解
            boolean isExcelDecimalValid = field.isAnnotationPresent(ExcelDecimalValid.class);
            if (isExcelDecimalValid) {
                if (isBigDecimal(fieldValue.toString())) {
                    BigDecimal cellDecimal = new BigDecimal(fieldValue.toString());
                    BigDecimal min = new BigDecimal(field.getAnnotation(ExcelDecimalValid.class).min());
                    BigDecimal max = new BigDecimal(field.getAnnotation(ExcelDecimalValid.class).max());
                    if (cellDecimal.compareTo(min) < 0) {
                        throw new ServiceException(String.format("第%s行字段过小，请核实", analysisContext.readRowHolder().getRowIndex() + 1));
                    }
                    if (cellDecimal.compareTo(max) > 0) {
                        throw new ServiceException(String.format("第%s行字段过大，请核实", analysisContext.readRowHolder().getRowIndex() + 1));
                    }
                } else {
                    throw new ServiceException(String.format("第%s行字段类型错误，请核实", analysisContext.readRowHolder().getRowIndex() + 1));
                }
            }
        }
        return true;
    }

    private static boolean isBigDecimal(String decimal) {
        try {
            BigDecimal bd = new BigDecimal(decimal);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }
}
